#include "GameBoard1.h"
GameBoard::GameBoard(int inWidth, int inHeight) :
	mWidth(inWidth), mHeight(inHeight)
{
	int i = 0;
	mCells = new GamePiece * [mWidth];
	
	try {
		for (i = 0; i < mWidth; i++) {
			mCells[i] = new GamePiece[mHeight];
		}
	}
	catch (...) {
		//Cleanup any memory we already allocated,because the destructor
		//will never get caled.The upper bound of the for loop is the
		//index of the last element in the mCells array that we tried
		//to allocate (the one that failed).All indices before that
		//one store pointers to allocated memory that must be freed.
		for (int j = 0; j < i; j++) {
			delete[] mCells[j];
		}
		delete[] mCells;
		mCells = nullptr;
		//Translate any exception to bad_alloc.
		throw bad_alloc();
	}
}
GameBoard::GameBoard(const GameBoard& src)
{
	copyFrom(src);
}
GameBoard::~GameBoard()
{
	//Free the old memory
	for (int i = 0; i < mWidth; i++) {
		delete[] mCells[i];
	}
	delete[] mCells;
	mCells = nullptr;
}

void GameBoard::copyFrom(const GameBoard& src)
{
	int i = 0;
	mWidth = src.mWidth;
	mHeight = src.mHeight;
	mCells = new GamePiece * [mWidth];
	
	try {
		for (int i = 0; i < mWidth; i++)
		{
			mCells[i] = new GamePiece[mHeight];
		}
	}
	catch (...) {
		//Clean up any memory we already allocated.
		//If this function is called from the copy constructor,
		//the destructor will never be called.
		//Use the same loop upper bound as described int the constructor.
		for (int j = 0; j < i; j++) {
			delete[] mCells[j];
		}
		delete[] mCells;
		// Set mCells and mWidth to values that will allow the 
		//destructor to run without harming anything.
		//This function is called from operator=,in which case the
		//object was already constructed,so the destructor will be
		//called at some point.
		mCells = nullptr;
		mWidth = 0;
		throw bad_alloc();
	}
	for (i = 0; i < mWidth; i++) {
		for (int j = 0; j < mHeight; j++) {
			mCells[i][j] = src.mCells[i][j];
		}
	}
}

GameBoard& GameBoard::operator=(const GameBoard& rhs)
{
	//Check for self-assignment
	if (this == &rhs) {
		return *this;
	}
	//Free the old memory
	for (int i = 0; i < mWidth; i++) {
		delete[] mCells[i];
	}
	delete[] mCells;
	mCells = nullptr;
	//Copy the new memory
	copyFrom(rhs);
	return *this;
}
void GameBoard::setPieceAt(int x, int y, const GamePiece& inElem)
{
	//Check for out of range arguments
	if (x < 0)
		throw out_of_range("GameBoard::setPieceAt: x-coord negative");
	if (x >= mWidth)
		throw out_of_range("GameBoard::setPieceAt: x-coord beyond width");
	if (y < 0)
		throw out_of_range("GameBoard::setPieceAt: y-coord negative");
	if (y >= mHeight)
		throw out_of_range("GameBoard::setPieceAt: y-coord beyond height");
	mCells[x][y] = inElem;
}


GamePiece& GameBoard::getPieceAt(int x, int y)
{
	return mCells[x][y];
}
const GamePiece& GameBoard::getPieceAt(int x, int y) const
{
	return mCells[x][y];
}